package com.yungam.imcs.controller.quality;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yungam.common.bean.process.ProductProcess;
import com.yungam.common.bean.product.ProductionProduct;
import com.yungam.common.bean.report.ReportRow;
import com.yungam.common.bean.report.ReportTableHeadItem;
import com.yungam.common.bean.report.TreeBean;
import com.yungam.common.response.RetDTO;
import com.yungam.common.service.ProductProcessService;
import com.yungam.common.service.ProductionProductService;
import com.yungam.common.service.ReportDataService;
import com.yungam.common.service.ReportTableHeadService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "报告管理页面接口")
@RestController
@RequestMapping("/reportManage")
public class ReportManageController {

    @Resource
    private ReportTableHeadService headService;
    @Resource
    private ReportDataService service;
    @Resource
    private ProductionProductService productService;
    @Resource
    private ProductProcessService processService;

    /* 查询 tree 数据 */
    @ApiOperation("查询 tree 数据")
    @GetMapping("/tree")
    public RetDTO<?> tree(@ApiParam("开始时间") String startTime,
                          @ApiParam("结束时间") String endTime,
                          @ApiParam("罐号") String productSn) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<TreeBean> treeBeanList = new ArrayList<>();
        QueryWrapper<ProductionProduct> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNotNull("end_time");
        if (StringUtils.isNotEmpty(productSn)) {
            queryWrapper.eq("product_sn", productSn);
        } else {
            if (StringUtils.isNotEmpty(startTime)) {
                queryWrapper.ge("end_time", startTime);
            }
            if (StringUtils.isNotEmpty(endTime)) {
                if (endTime.length() == 10) { //格式yyyy-MM-dd(没有时分秒)
                    endTime += " 99"; //endTime为包含
                }
                queryWrapper.le("end_time", endTime);
            }
        }
        List<ProductionProduct> list = productService.list(queryWrapper);
        Map<String, List<ProductionProduct>> productMap = list.stream().collect(Collectors.groupingBy(productionProduct -> sdf.format(productionProduct.getEndTime())));
        productMap.forEach((date, productList) -> {
            TreeBean treeBean = new TreeBean();
            treeBean.setName(date);
            List<TreeBean.Product> productChildren = productList.stream().map(product -> {
                TreeBean.Product product0 = new TreeBean.Product();
                product0.setName(product.getProductSn());
                List<TreeBean.Process> processChildren = processService.list(new QueryWrapper<ProductProcess>().eq("product_no", product.getProductNo())).stream().map(process -> {
                    TreeBean.Process process0 = new TreeBean.Process();
                    process0.setProcessNo(process.getProcessNo());
                    process0.setName(process.getProcessName());
                    return process0;
                }).collect(Collectors.toList());
                product0.setChildren(processChildren);
                return product0;
            }).collect(Collectors.toList());
            treeBean.setChildren(productChildren);
            treeBeanList.add(treeBean);
        });
        return RetDTO.data(treeBeanList);
    }

    /* 查询表头 */
    @ApiOperation("查询表头数据")
    @GetMapping("/tableHead")
    public RetDTO<?> getTableHeadData() {
        List<Map<String, Object>> all1 = new ArrayList<>(), all2 = new ArrayList<>();
        QueryWrapper<ReportTableHeadItem> qw = new QueryWrapper<ReportTableHeadItem>().eq("trash", false);
        List<ReportTableHeadItem> list = headService.list(qw);
        // map
        Map<Integer, List<Map<String, Object>>> map = this.buildFatherTitle(list);
        // 所有的一级标题
        List<ReportTableHeadItem> firstLevels = list.stream().filter(v -> v.getLevel() == 1).collect(Collectors.toList());
        for (ReportTableHeadItem ri : firstLevels) {
            Map<String, Object> cur = new HashMap<>();
            if (!ri.getIsFatherTitle()) {
                cur.put("field", ri.getField());
                Map<String, String> render = new HashMap<>();
                render.put("name", ri.getEditRender());
                cur.put("editRender", render);
                cur.put("width", 200);
            } else {
                List<Map<String, Object>> toSort = map.get(ri.getId());
                toSort.sort(Comparator.comparingInt(a -> (Integer) a.get("order")));
                cur.put("children", map.get(ri.getId()));
            }
            cur.put("title", ri.getTitle());
            cur.put("order", ri.getOrder());
            if (ri.getReportType() == 1) all1.add(cur);
            else all2.add(cur);
        }
        // 按表区分, 按 order 排序
        all1.sort(Comparator.comparingInt(a -> (Integer) a.get("order")));
        all2.sort(Comparator.comparingInt(a -> (Integer) a.get("order")));
        Map<Integer, List<Map<String, Object>>> ans = new HashMap<>();
        ans.put(1, all1);
        ans.put(2, all2);
        return RetDTO.data(ans);
    }

    /*
     * Util
     * 整理父级标题
     * */
    private Map<Integer, List<Map<String, Object>>> buildFatherTitle(List<ReportTableHeadItem> cur) {
        // 子级 field
        List<ReportTableHeadItem> sonFields = cur.stream().filter(v -> !v.getIsFatherTitle() && v.getLevel() != 1).collect(Collectors.toList());
        // Map
        Map<Integer, List<Map<String, Object>>> map = new HashMap<>();
        for (ReportTableHeadItem item : sonFields) {
            int parentId = item.getParentId();
            List<Map<String, Object>> list = map.getOrDefault(parentId, new ArrayList<>());
            Map<String, Object> son = new HashMap<>();
            son.put("field", item.getField());
            son.put("title", item.getTitle());
            Map<String, String> render = new HashMap<>();
            render.put("name", item.getEditRender());
            son.put("editRender", render);
            son.put("order", item.getOrder());
            son.put("width", 200);
            list.add(son);
            map.put(parentId, list);
        }
        return map;
    }

    /* 查询报告数据
     *    Params:
     *       reportType: 报告类型 （*）
     *       queryType: 查询类型 （*）『'date', 'product', 'process'』
     *       keyword: 过滤的关键值  (queryType === 'date' || 'product')
     *       List<String> products: 要查询的products  (queryType === 'date')
     *       productSn: 产品编号 (queryType === 'product' || 'process')
     *       processNo: 工序编号 (queryType === 'process')
     * */
    @ApiOperation("查询报告数据")
    @GetMapping("/getReportData")
    public RetDTO<List<ReportRow>> getReportData(String reportType, String queryType, String keyword,
                                                 @RequestParam(required = false) List<String> products, String productSn, String processNo) {
        QueryWrapper<ReportRow> qw = new QueryWrapper<>();
        qw.eq("report_type", reportType);
        qw.eq("is_deleted", false);
        if (Objects.equals(queryType, "process")) {
            qw.eq("product_sn", productSn);
            qw.eq("process_no", processNo);
        }
        if (Objects.equals(queryType, "product")) {
            qw.eq("product_sn", productSn);
            qw.like(StringUtils.isNotBlank(keyword), "process_no", keyword);
        }
        if (Objects.equals(queryType, "date")) {
            qw.in("product_sn", products);
            qw.like(StringUtils.isNotBlank(keyword), "process_no", keyword);
        }
        qw.orderByDesc("create_time"); // 时间降序
        List<ReportRow> ans = service.list(qw);
        return RetDTO.data(ans);
    }

    /* 保存报告数据 */
    @ApiOperation("保存报告数据")
    @PostMapping("/saveRows")
    public RetDTO<?> saveRows(@RequestBody Map<String, Object> params) {
        List<Map<String, Object>> add = (List<Map<String, Object>>) params.get("add"),
                update = (List<Map<String, Object>>) params.get("update");
        String reportType = String.valueOf(params.getOrDefault("reportType", "")),
                productSn = (String) params.getOrDefault("productSn", ""),
                processNo = (String) params.getOrDefault("processNo", "");
        if (add != null && add.size() > 0) {
            for (Map<String, Object> map : add) {
                ReportRow row = new ReportRow(productSn, processNo);
                row.setData(map);
                row.setReportType(Integer.parseInt(reportType));
                row.setCreateTime(new Date());
                row.setIsDeleted(false);
                service.save(row);
            }
        }
        if (update != null && update.size() > 0) {
            for (Map<String, Object> map : update) {
                ReportRow row = new ReportRow();
                row.setId((Integer) map.get("id"));
                row.setData(map);
                service.updateById(row);
            }
        }
        return RetDTO.success();
    }

    /* 删除报告数据 */
    @ApiOperation("删除报告数据")
    @DeleteMapping("/deleteRows")
    public RetDTO<?> deleteRows(@RequestParam(required = false) List<Integer> ids) {
        for (Integer id : ids) {
            ReportRow row = new ReportRow();
            row.setId(id);
            row.setIsDeleted(true);
            service.updateById(row);
        }
        return RetDTO.success();
    }

    /* 按类型删除整个报告
     *    Params:
     *       reportType: 报告类型 （*）
     *       delType: 查询类型 （*）『'date', 'product', 'process'』
     *       List<String> products: 要删除的products  (queryType === 'date')
     *       productSn: 产品编号 (queryType === 'product' || 'process')
     *       processNo: 工序编号 (queryType === 'process')
     * */
    @ApiOperation("按类型删除整个报告")
    @DeleteMapping("/delReport")
    public RetDTO<?> delReport(String reportType, String delType, @RequestParam(required = false) List<String> products,
                               String productSn, String processNo) {
        UpdateWrapper<ReportRow> uw = new UpdateWrapper<>();
        uw.eq("report_type", reportType); // 设置报告类型
        if (Objects.equals(delType, "process")) {
            uw.eq("product_sn", productSn).eq("process_no", processNo);
        }
        if (Objects.equals(delType, "product")) {
            uw.eq("product_sn", productSn);
        }
        if (Objects.equals(delType, "date")) {
            uw.in("product_sn", products);
        }
        uw.set("is_deleted", true);
        service.update(null, uw);
        return RetDTO.success();
    }

}
